/**
 * 
 */
package edu.uwm.nlp.jude.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import edu.uwm.nlp.jude.util.StringUtil;

/**
 * @author qing
 *
 * Jun 15, 2009
 */
public class StringIDAnalyzer {
	
	private String fullRef;
	
	public StringIDAnalyzer(String fullRef)
	{
		this.fullRef = fullRef;
	}
	
	public ArrayList<ReferenceEntity> forkStringId()
	{
		int nextStartIdx = fullRef.indexOf('\n');
		int curStartIdx = nextStartIdx;
		int curIdx = curStartIdx;
		int i =0;
		String[] yearPar;
		String[] nextYearPar;
		ReferenceEntity entity;
		String idStr;
		ArrayList<ReferenceEntity> rEntList = new ArrayList<ReferenceEntity>();
		String refStr = null;
		
		while(curIdx != -1)
		{
			i++;
			yearPar = this.findYearIdx(curIdx);
			if(yearPar[2]==null)
			{
				System.err.println("Not a reference section with author format.");
				break;
			}
			else
			{
				curStartIdx = this.findStartIdx(Integer.parseInt(yearPar[0]));
				nextYearPar = this.findYearIdx(Integer.parseInt(yearPar[1]));
				
				if(nextYearPar[1].equals("-1")) // end of the citation list
				{
					refStr = fullRef.substring(Integer.parseInt(yearPar[0])+1, Integer.parseInt(nextYearPar[0]));
					idStr = findName(curStartIdx)+","+yearPar[2];
					System.out.println(idStr+"=="+refStr);
					break;
				}
				nextStartIdx = findStartIdx(Integer.parseInt(nextYearPar[0]));
				while(nextStartIdx != -1 && curStartIdx == nextStartIdx)
				{
					nextYearPar = findYearIdx(Integer.parseInt(nextYearPar[1]));
					nextStartIdx = findStartIdx(Integer.parseInt(nextYearPar[0]));
				}
				if(nextStartIdx <0 && curStartIdx >=0)
					refStr = fullRef.substring(curStartIdx);
				else if(nextStartIdx> 0 && curStartIdx >=0)
					refStr = fullRef.substring(curStartIdx, nextStartIdx);
				
				String nameCand = findName(curStartIdx);
				idStr = nameCand+","+yearPar[2];
				if(refStr !=null && nameCand != null)
				{
					entity = new ReferenceEntity(idStr,refStr);
					rEntList.add(entity);
					System.out.println(idStr+"=="+refStr);
				}
				
				
				curIdx = Integer.parseInt(nextYearPar[0]);
			}
			
		}
		return rEntList;
	}
	
	
	public String[] findYearIdx(int index)
	{
		int curRetIdx = fullRef.indexOf('\n',index);
		int nextRetIdx = fullRef.indexOf('\n', curRetIdx+1);
		String year = null;
		
		while(curRetIdx!=-1 && nextRetIdx != -1)
		{
			Pattern p = Pattern.compile("(19|20)[0-9]{2}[a-z]?");
								// sometimes year might be 2007a, to distinguish the same author and year citation
			Matcher m = p.matcher(fullRef.substring(curRetIdx+1, nextRetIdx));
			if(m.find())
			{
				year = m.group();
				break;
			}
			else
			{
				curRetIdx = nextRetIdx;
				nextRetIdx = fullRef.indexOf('\n',curRetIdx+1);
			}
		}
		
		String[] yearPar = {(new Integer(curRetIdx)).toString(),(new Integer(nextRetIdx)).toString(),year};
		return yearPar;
	}
	
	/**
	 * find the start index of the citation.
	 * the algorithm scan backwards from year, the line with significant offset will be considered as the
	 * end of the previous citation.
	 * @param idx position of the year. or the position of ( if there is before year.
	 * @return start index of current citation
	 */
	public int findStartIdx(int idx)
	{
		int index = idx;
		if(index <= 2) return index;
							//already the start, but very rear, means a citation started with year
		
		int preIdx;
		int prepreIdx;
		int startCand;
		
		while(index > 0)
		{
			preIdx = fullRef.lastIndexOf('\n',index);
			startCand = preIdx;
			while(preIdx >0 && (fullRef.charAt(preIdx)=='\r')||fullRef.charAt(preIdx)==' ')
				preIdx--;
			preIdx = preIdx==startCand?preIdx-1:preIdx;
			if(preIdx <0) // if it is first citation 
				return 0;
			prepreIdx = fullRef.lastIndexOf('\n',preIdx-1);
			if(prepreIdx == -1) // might be ignored
				return 0;
			else
			{
				String namesCand = fullRef.substring(prepreIdx, preIdx);
				if(StringUtil.isAllNames(namesCand) && 
						namesCand.length() > StringUtil.getCurrentLine(fullRef, index).length() /2f)
				{
					index = preIdx-1;
				}
				else
					return startCand+1;
			}
			
		}
		return index;
	}
	
	public String findName(int index)
	{
		int idx0 = fullRef.indexOf(' ',index);
		int idx1 = fullRef.indexOf(',', index);
		int idx2 = fullRef.indexOf('.', index);
		if(index<=0) return null;
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(idx0);
		list.add(idx1);
		list.add(idx2);
		Collections.sort(list);
		int endIdx =-1;
		for(Integer i:list)
		{
			if(i>=0)
			{
				endIdx =  i;
				break;
			}
		}
		
		String nameCand;
		if(endIdx<1)
			nameCand = fullRef.substring(index).trim();
		if(index>endIdx)return null;
		nameCand = fullRef.substring(index, endIdx).trim();
		if(nameCand.matches("[A-Za-z.,\\-]*"))
			return nameCand;
		else
			return null;
	}
	
}
